use crate::db::dao;
use crate::service::auth::{AuthService, DefaultAuthService};
use crate::service::auth_token::DefaultAuthTokenService;
use crate::service::candidate_path::DefaultCandidatePathService;
use crate::service::candidate_path_manager::{
    CandidatePathManagerService, DefaultCandidatePathManagerService,
};
use crate::service::candidate_path_segment_list::DefaultCandidatePathSegmentListService;
use crate::service::candidate_path_segment_list_manager::{
    CandidatePathSegmentListManagerService, DefaultCandidatePathSegmentListManagerService,
};
use crate::service::network_acl::DefaultNetworkAclService;
use crate::service::network_acl_manager::{
    DefaultNetworkAclManagerService, NetworkAclManagerService,
};
use crate::service::network_acl_rule::{DefaultNetworkAclRuleService, NetworkAclRuleService};
use crate::service::segment::DefaultSegmentService;
use crate::service::segment_list::DefaultSegmentListService;
use crate::service::segment_list_manager::{
    DefaultSegmentListManagerService, SegmentListManagerService,
};
use crate::service::te_policy_group::{DefaultTePolicyGroupService, TePolicyGroupService};
use crate::service::traffic_steering_rule::{
    DefaultTrafficSteeringRuleService, TrafficSteeringRuleService,
};
use crate::service::user::DefaultUserService;
use crate::service::{
    endpoint::DefaultEndpointService,
    endpoint_manager::{DefaultEndpointManagerService, EndpointManagerService},
    endpoint_peer::DefaultEndpointPeerService,
    endpoint_peer_manager::{DefaultEndpointPeerManagerService, EndpointPeerManagerService},
    endpoint_peer_wireguard_config::DefaultEndpointPeerWireguardConfigService,
    endpoint_peer_wireguard_config_manager::{
        DefaultEndpointPeerWireguardConfigManagerService, EndpointPeerWireguardConfigManagerService,
    },
    endpoint_srv6_config::{DefaultEndpointSrv6ConfigService, EndpointSrv6ConfigService},
    endpoint_wireguard_config::{
        DefaultEndpointWireguardConfigService, EndpointWireguardConfigService,
    },
};
use std::sync::Arc;

pub struct ServiceSet {
    pub auth: Arc<dyn AuthService>,
    pub endpoint_manager: Arc<dyn EndpointManagerService>,
    pub endpoint_srv6_config: Arc<dyn EndpointSrv6ConfigService>,
    pub endpoint_wireguard_config: Arc<dyn EndpointWireguardConfigService>,
    pub endpoint_peer_manager: Arc<dyn EndpointPeerManagerService>,
    pub endpoint_peer_wireguard_config_manager: Arc<dyn EndpointPeerWireguardConfigManagerService>,
    pub te_policy_group: Arc<dyn TePolicyGroupService>,
    pub candidate_path_manager: Arc<dyn CandidatePathManagerService>,
    pub candidate_path_segment_list_manager: Arc<dyn CandidatePathSegmentListManagerService>,
    pub segment_list_manager: Arc<dyn SegmentListManagerService>,
    pub network_acl_manager: Arc<dyn NetworkAclManagerService>,
    pub network_acl_rule: Arc<dyn NetworkAclRuleService>,
    pub traffic_steering_rule: Arc<dyn TrafficSteeringRuleService>,
}

impl ServiceSet {
    pub fn new(dao_set: dao::DaoSet, redis_conn: redis::aio::MultiplexedConnection) -> Self {
        let user_service = Arc::new(DefaultUserService::new(dao_set.user));
        let auth_token_service = Arc::new(DefaultAuthTokenService::new(redis_conn.clone()));
        let auth_service = Arc::new(DefaultAuthService::new(
            user_service.clone(),
            auth_token_service.clone(),
            redis_conn.clone(),
        ));

        let endpoint_service = Arc::new(DefaultEndpointService::new(dao_set.endpoint));

        let endpoint_srv6_config_service = Arc::new(DefaultEndpointSrv6ConfigService::new(
            dao_set.endpoint_srv6_config,
        ));

        let endpoint_wireguard_config_service = Arc::new(
            DefaultEndpointWireguardConfigService::new(dao_set.endpoint_wireguard_config),
        );
        let endpoint_peer_wireguard_config_service = Arc::new(
            DefaultEndpointPeerWireguardConfigService::new(dao_set.endpoint_peer_wireguard_config),
        );

        let endpoint_peer_service =
            Arc::new(DefaultEndpointPeerService::new(dao_set.endpoint_peer));

        let endpoint_peer_wireguard_config_manager_service =
            Arc::new(DefaultEndpointPeerWireguardConfigManagerService::new(
                endpoint_wireguard_config_service.clone(),
                endpoint_peer_service.clone(),
                endpoint_peer_wireguard_config_service.clone(),
            ));

        let endpoint_peer_manager_service = Arc::new(DefaultEndpointPeerManagerService::new(
            endpoint_service.clone(),
            endpoint_peer_service.clone(),
            endpoint_peer_wireguard_config_manager_service.clone(),
        ));

        let endpoint_manager_service = Arc::new(DefaultEndpointManagerService::new(
            endpoint_service,
            endpoint_srv6_config_service.clone(),
            endpoint_wireguard_config_service.clone(),
            endpoint_peer_manager_service.clone(),
        ));

        let segment_service = Arc::new(DefaultSegmentService::new(dao_set.segment));

        let segment_list_service = Arc::new(DefaultSegmentListService::new(dao_set.segment_list));

        let segment_list_manager_service = Arc::new(DefaultSegmentListManagerService::new(
            segment_list_service,
            segment_service,
        ));

        let candidate_path_segment_list_service = Arc::new(
            DefaultCandidatePathSegmentListService::new(dao_set.candidate_path_segment_list),
        );

        let candidate_path_segment_list_manager_service =
            Arc::new(DefaultCandidatePathSegmentListManagerService::new(
                candidate_path_segment_list_service,
                segment_list_manager_service.clone(),
            ));

        let candidate_path_service =
            Arc::new(DefaultCandidatePathService::new(dao_set.candidate_path));

        let candidate_path_manager_service = Arc::new(DefaultCandidatePathManagerService::new(
            candidate_path_service,
            candidate_path_segment_list_manager_service.clone(),
        ));

        let te_policy_group_service =
            Arc::new(DefaultTePolicyGroupService::new(dao_set.te_policy_group));

        let network_acl_service = Arc::new(DefaultNetworkAclService::new(dao_set.network_acl));
        let network_acl_rule_service =
            Arc::new(DefaultNetworkAclRuleService::new(dao_set.network_acl_rule));

        let network_acl_manager_service = Arc::new(DefaultNetworkAclManagerService::new(
            network_acl_service,
            network_acl_rule_service.clone(),
        ));

        let traffic_steering_rule_service = Arc::new(DefaultTrafficSteeringRuleService::new(
            dao_set.traffic_steering_rule,
        ));
        Self {
            auth: auth_service,
            endpoint_manager: endpoint_manager_service,
            endpoint_srv6_config: endpoint_srv6_config_service,
            endpoint_peer_manager: endpoint_peer_manager_service,
            endpoint_wireguard_config: endpoint_wireguard_config_service,
            endpoint_peer_wireguard_config_manager: endpoint_peer_wireguard_config_manager_service,
            te_policy_group: te_policy_group_service,
            candidate_path_manager: candidate_path_manager_service,
            candidate_path_segment_list_manager: candidate_path_segment_list_manager_service,
            segment_list_manager: segment_list_manager_service,
            network_acl_manager: network_acl_manager_service,
            network_acl_rule: network_acl_rule_service,
            traffic_steering_rule: traffic_steering_rule_service,
        }
    }
}
